﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Input;
using Amazon.SimpleDB;
using Amazon.SimpleDB.Model;

namespace SimpleDbBrowser.ViewModel
{
    /// <summary>
    /// The view model providing the UI for the CreateDomain task.
    /// </summary>
    public sealed class CreateDomainViewModel : ViewModelBase
    {
        private readonly AmazonSimpleDB db;
        private string name;

        /// <summary>
        /// Initializes a new instance of the CreateDomainViewModel class.
        /// </summary>
        /// <param name="database">
        /// The simpleDB that this view model will interact with.
        /// </param>
        public CreateDomainViewModel(AmazonSimpleDB database)
        {
            Debug.WriteLine("Creating CreateDomainViewModel");

            if (database == null) throw new ArgumentNullException("database");
            this.db = database;

            this.DisplayName = "Create a new domain";

            this.CreateDomain = new RelayCommand(this.OnCreateDomain, this.CanCreateDomain);
        }

        /// <summary>
        /// Gets the command that creates a domain.
        /// </summary>
        public ICommand CreateDomain { get; private set; }

        /// <summary>
        /// Gets or sets the name of the domain that will be created.
        /// </summary>
        public string DomainName
        {
            get { return this.name; }

            set
            {
                if (this.name == value) return;

                this.name = value;
                this.OnPropertyChanged("DomainName");
                Debug.WriteLine(string.Format("CreateDomainViewModel.DomainName set to {0}.", this.name));
            }
        }

        /// <summary>
        /// Fires when a domain has been created.
        /// </summary>
        public event EventHandler DomainCreated;

        /// <summary>
        /// Creates a domain in the simpledb.
        /// </summary>
        /// <param name="param">
        /// This is not used.
        /// </param>
        /// <remarks>
        /// The created domain uses the DomainName property to select the 
        /// domain's name.
        /// </remarks>
        private void OnCreateDomain(object param)
        {
            var dmnName = this.DomainName;
            var worker = new BackgroundWorker();
            worker.DoWork += (o, a) =>
                             {
                                 var req = new CreateDomainRequest().WithDomainName(dmnName);
                                 var resp = this.db.CreateDomain(req);
                             };

            worker.RunWorkerCompleted += (s, o) => this.OnDomainCreated(EventArgs.Empty);

            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Determines whether the domain can currently be created.
        /// </summary>
        /// <param name="param">
        /// This is not used.
        /// </param>
        /// <returns>
        /// True if a domain can be created, otherwise false.
        /// </returns>
        /// <remarks>
        /// The general reason a domain cannot be created is that the supplied
        /// domain name is obviously invalid.
        /// </remarks>
        private bool CanCreateDomain(object param)
        {
            return !string.IsNullOrWhiteSpace(this.DomainName);
        }

        /// <summary>
        /// Perform actions that must be done once a domain has been created.
        /// </summary>
        /// <param name="args">
        /// This is not used.
        /// </param>
        private void OnDomainCreated(EventArgs args)
        {
            var tmp = this.DomainCreated;
            if (tmp != null)
            {
                tmp(this, args);
            }

            // Clear the domain name if it's been created successfully
            this.DomainName = string.Empty;

            return;
        }
    }
}